`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date:    16:29:15 07/08/2015 
// Design Name: 
// Module Name:    Pipeline 
// Project Name: 
// Target Devices: 
// Tool versions: 
// Description: 
//
// Dependencies: 
//
// Revision: 
// Revision 0.01 - File Created
// Additional Comments: 
//
//////////////////////////////////////////////////////////////////////////////////
module Pipeline(
	input clk,enable,//enable2,
	input reset,
	output [31:0] salida
/*	output [31:0] salidaInst,
	output [31:0] salidaL1,
	output mux,
	output otracosa*/
	
    );

//assign salida = salidaE5E5E2;
/*assign salidaInst = instructionE1L1;
assign salidaL1 = E1AdderE1L1;
assign mux = RegWriteE3L3;
assign otracosa = RegWriteL3E4;*/
//assign salidaL1 = E1AdderE1L1;

//Etapa1 Latch1
wire [31:0] instructionE1L1;
wire [31:0] E1AdderE1L1;
//Latch1 Etapa2
wire [31:0] instructionL1E2;
wire [31:0] E1AdderL1E2;
//Etapa2 Latch2
wire RegDstE2L2;
wire RegWriteOE2L2;
wire ALUSrcE2L2;
wire PCSrcE2L2;
wire MemReadE2L2;
wire [3:0] MemWriteE2L2;
wire MemToRegE2L2;
wire [1:0] ALUOpE2L2;
wire jmpE2E1;
wire [2:0] LoadOpE2L2;
wire [1:0] StoreOpE2L2;
wire [2:0] InmCtrlE2L2;
wire [31:0] E2AdderE2L2;
wire [31:0] ReadData1E2L2;
wire [31:0] ReadData2E2L2;
wire [31:0] ExtSigE2L2;
wire [4:0] RTE2L2;
wire [4:0] RDE2L2;
wire [4:0] RSE2L2;
wire [31:0] jmpAddrE2E1;
//Latch 2 ETAPA 3
wire RegDstL2E3;
wire RegWriteOL2E3;
wire ALUSrcL2E3;
wire PCSrcL2E3;
wire MemReadL2E3;
wire [3:0] MemWriteL2E3;
wire MemToRegL2E3;
wire [1:0] ALUOpL2E3;
wire [2:0] LoadOpL2E3;
wire [1:0] StoreOpL2E3;
wire [2:0] InmCtrlL2E3;
wire [31:0] E2AdderL2E3;
wire [31:0] ReadData1L2E3;
wire [31:0] ReadData2L2E3;
wire [31:0] ExtSigL2E3;
wire [4:0] RTL2E3;
wire [4:0] RDL2E3;
wire [4:0] RSL2E3;
wire jmpL2E3;
wire ympE3L2;
//Etapa3 Latch3
wire [31:0] salidaALUE3L3;
wire zeroFlagE3L3;
wire [31:0] salidaAdderE3L3;
wire [4:0] salidaMuxE3L3;
wire [31:0] Data2E3L3;
wire RegWriteE3L3;
wire PCSrc1E3L3;
wire MemRead1E3L3;
wire [3:0] MemWrite1E3L3;
wire MemToReg1E3L3;
wire [2:0] LoadOp1E3L3;

// Latch3 Etapa4
wire [31:0] salidaALUL3E4;
wire zeroFlagL3E4;
wire [31:0] salidaAdderL3E4;
wire [4:0] salidaMuxL3E4;
wire [31:0] Data2L3E4;
wire RegWriteL3E4;
wire PCSrc1L3E4;
wire MemRead1L3E4;
wire [3:0] MemWrite1L3E4;
wire MemToReg1L3E4;
wire [2:0] LoadOp1L3E4;

//Etapa4 Latch4
wire [31:0] salidaE4E4L4;
wire PCSrcE4E1;
wire [31:0] salidaAdder1E4E1;
wire [4:0] salidaMux1E4L4;
wire RegWrite1E4L4;
wire MemToRegE4L4;
wire [31:0] ALUdataE4L4;

//Lacht 4 Etapa 5
wire [31:0] salidaE4L4E5;
wire [4:0] salidaMux1L4E5;
wire RegWrite1L4E5;
wire MemToRegL4E5;
wire [31:0] ALUdataL4E5;

//Etapa5 Etapa 2
wire [4:0] salidaMuxE5E2;
wire RegWriteE5E2;
wire [31:0] salidaE5E5E2;

//ForwardingUnit
wire [1:0] fA;
wire [1:0] fB;
wire stallone;

Etapa1 etapa1(
.PCSrc(PCSrcE4E1),
.clk(clk),
.reset(reset),
.stallone(stallone),
.jmpAddr(jmpAddrE2E1),
.jmp(jmpE2E1),
.BranchData(salidaAdder1E4E1),
.Instruccion(instructionE1L1),
.E1Adder(E1AdderE1L1),
.enable(enable),
.PcOutsider(salida)
);

LatchIFID IDIF( 			//TA
.InstruccionIn(instructionE1L1),
.E1AdderIn(E1AdderE1L1),
.stallone(stallone),
.clk(clk),
.InstruccionOut(instructionL1E2),
.E1AdderOut(E1AdderL1E2)
);


Etapa2 etapa2(
.instruccion(instructionL1E2),
.E1Adder(E1AdderL1E2),
.DestinoReg(salidaMuxE5E2),
.WriteData(salidaE5E5E2),
.RegWrite(RegWriteE5E2),
.clk(clk),
.RegDst(RegDstE2L2),
.RegWriteO(RegWriteOE2L2),
.ALUSrc(ALUSrcE2L2), 
.PCSrc(PCSrcE2L2),
.MemRead(MemReadE2L2),
.MemWrite(MemWriteE2L2),
.MemToReg(MemToRegE2L2),
.ALUOp(ALUOpE2L2), 
.jmp(jmpE2E1), 
.LoadOp(LoadOpE2L2), 
.StoreOp(StoreOpE2L2), 
.InmCtrl(InmCtrlE2L2),
.E2Adder(E2AdderE2L2),
.ReadData1(ReadData1E2L2),
.ReadData2(ReadData2E2L2),
.ExtSig(ExtSigE2L2),
.RT(RTE2L2),
.RD(RDE2L2),
.RS(RSE2L2),
.jmpAddr(jmpAddrE2E1));


LatchIDEX IDEX(
.RegDstIn(RegDstE2L2), 
.RegWriteOIn(RegWriteOE2L2),
.ALUSrcIn(ALUSrcE2L2), 
.PCSrcIn(PCSrcE2L2),
.MemReadIn(MemReadE2L2),
.MemWriteIn(MemWriteE2L2),
.MemToRegIn(MemToRegE2L2),
.ALUOpIn(ALUOpE2L2),  
.LoadOpIn(LoadOpE2L2), 
.StoreOpIn(StoreOpE2L2), 
.InmCtrlIn(InmCtrlE2L2),
.E2AdderIn(E2AdderE2L2),
.ReadData1In(ReadData1E2L2),
.ReadData2In(ReadData2E2L2),
.ExtSigIn(ExtSigE2L2),
.RTIn(RTE2L2),
.RDIn(RDE2L2),
.RSIn(RSE2L2),
.yamp(ympE3L2),
.vranch(PCSrcE4E1),
.stallone(stallone),
.clk(clk),
.RegDstOut(RegDstL2E3), 
.RegWriteOOut(RegWriteOL2E3),
.ALUSrcOut(ALUSrcL2E3), 
.PCSrcOut(PCSrcL2E3),
.MemReadOut(MemReadL2E3),
.MemWriteOut(MemWriteL2E3),
.MemToRegOut(MemToRegL2E3),
.ALUOpOut(ALUOpL2E3), 
.LoadOpOut(LoadOpL2E3), 
.StoreOpOut(StoreOpL2E3), 
.InmCtrlOut(InmCtrlL2E3),
.E2AdderOut(E2AdderL2E3),
.ReadData1Out(ReadData1L2E3),
.ReadData2Out(ReadData2L2E3),
.ExtSigOut(ExtSigL2E3),
.RTOut(RTL2E3),
.RDOut(RDL2E3),
.RSOut(RSL2E3),
.jmpOut(jmpL2E3),
.jmpIn(jmpE2E1)
);


Etapa3 etapa3(	
.RegDst(RegDstL2E3),
.RegWriteO(RegWriteOL2E3),
.ALUSrc(ALUSrcL2E3), 
.PCSrc(PCSrcL2E3),
.MemRead(MemReadL2E3),
.MemWrite(MemWriteL2E3),
.MemToReg(MemToRegL2E3),
.ALUOp(ALUOpL2E3), 
.LoadOp(LoadOpL2E3),
.StoreOp(StoreOpL2E3),
.InmCtrl(InmCtrlL2E3),
.E2Adder(E2AdderL2E3),
.ReadData1(ReadData1L2E3),
.ReadData2(ReadData2L2E3),
.ExtSig(ExtSigL2E3),
.RT(RTL2E3),
.RD(RDL2E3),
.DataE4(salidaALUL3E4),
.DataE5(salidaE5E5E2),
.forwardA(fA),
.forwardB(fB),
.salidaALU(salidaALUE3L3),
.zeroFlag(zeroFlagE3L3),
.salidaAdder(salidaAdderE3L3),
.salidaMux(salidaMuxE3L3),
.Data2(Data2E3L3),
.RegWrite(RegWriteE3L3),
.PCSrc1(PCSrc1E3L3),
.MemRead1(MemRead1E3L3),
.MemWrite1(MemWrite1E3L3),
.MemToReg1(MemToReg1E3L3),
.LoadOp1(LoadOp1E3L3),
.jmpIn(jmpL2E3),
.jmpOut(ympE3L2)
);

LatchEXMEM EXMEM(
.salidaALUIn(salidaALUE3L3),
.zeroFlagIn(zeroFlagE3L3),
.salidaAdderIn(salidaAdderE3L3),
.salidaMuxIn(salidaMuxE3L3),
.Data2In(Data2E3L3),
.RegWriteIn(RegWriteE3L3),
.PCSrc1In(PCSrc1E3L3),
.MemRead1In(MemRead1E3L3),
.MemWrite1In(MemWrite1E3L3),
.MemToReg1In(MemToReg1E3L3),
.LoadOp1In(LoadOp1E3L3),
.vranch(PCSrcE4E1),
.clk(clk),
.salidaALUOut(salidaALUL3E4),
.zeroFlagOut(zeroFlagL3E4),
.salidaAdderOut(salidaAdderL3E4),
.salidaMuxOut(salidaMuxL3E4),
.Data2Out(Data2L3E4),
.RegWriteOut(RegWriteL3E4),
.PCSrc1Out(PCSrc1L3E4),
.MemRead1Out(MemRead1L3E4),
.MemWrite1Out(MemWrite1L3E4),
.MemToReg1Out(MemToReg1L3E4),
.LoadOp1Out(LoadOp1L3E4)
);

Etapa4 etapa4(
.salidaALU(salidaALUL3E4),
.zeroFlag(zeroFlagL3E4),
.salidaAdder(salidaAdderL3E4),
.salidaMux(salidaMuxL3E4),
.Data2(Data2L3E4),
.RegWrite(RegWriteL3E4),
.PCSrc1(PCSrc1L3E4),
.MemRead1(MemRead1L3E4),
.MemWrite1(MemWrite1L3E4),
.MemToReg1(MemToReg1L3E4),
.LoadOp1(LoadOp1L3E4),
.clk(clk),
.salidaE4(salidaE4E4L4),
.PCSrc(PCSrcE4E1),
.salidaAdder1(salidaAdder1E4E1),
.salidaMux1(salidaMux1E4L4),
.RegWrite1(RegWrite1E4L4),
.MemToReg(MemToRegE4L4),
.ALUdata(ALUdataE4L4)
);

LatchMEMWB MEMWB(
.salidaE4In(salidaE4E4L4),
.salidaMux1In(salidaMux1E4L4),
.RegWrite1In(RegWrite1E4L4),
.MemToRegIn(MemToRegE4L4),
.ALUdataIn(ALUdataE4L4),
.clk(clk),
.salidaE4Out(salidaE4L4E5),
.salidaMux1Out(salidaMux1L4E5),
.RegWrite1Out(RegWrite1L4E5),
.MemToRegOut(MemToRegL4E5),
.ALUdataOut(ALUdataL4E5)
);

Etapa5 etapa5(
.salidaE4(salidaE4L4E5),
.salidaMux1(salidaMux1L4E5),
.RegWrite1(RegWrite1L4E5),
.MemToReg(MemToRegL4E5),
.ALUdata(ALUdataL4E5),
.salidaMux(salidaMuxE5E2),
.RegWrite(RegWriteE5E2),
.salidaE5(salidaE5E5E2)
);

ForwardingUnit FU(
.Rs(RSL2E3),
.Rt(RTL2E3),
.RdE4(salidaMuxL3E4),
.RdE5(salidaMuxE5E2),
.regWriteE4(RegWriteL3E4),
.regWriteE5(RegWriteE5E2),
.forwardA(fA),
.forwardB(fB)
);

HazardUnit HU(
.memReadE3(MemReadL2E3),
.RtE3(RTL2E3),
.RsE2(RSE2L2),
.RtE2(RTE2L2),
.stallone(stallone)
);
endmodule
